package com.seuic.scanner2d;

import java.io.UnsupportedEncodingException;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;

import android.content.Context;

import com.motorolasolutions.adc.decoder.BarCodeReader;
import com.motorolasolutions.adc.decoder.BarCodeReader.DecodeCallback;
import com.motorolasolutions.adc.decoder.BarCodeReader.PictureCallback;
import com.motorolasolutions.adc.decoder.BarCodeReader.PreviewCallback;
import com.motorolasolutions.adc.decoder.BarCodeReader.ReaderInfo;
import com.seuic.scanner2d.pojo.BarcodeInfo;
import com.seuic.scanner2d.type.Scanner2DBarcodeType;
import com.seuic.scanner2d.type.Scanner2DModeType;
import com.seuic.scanner2d.utils.StringUtils;

public class Scanner2D4500Manager implements DecodeCallback, PictureCallback, PreviewCallback {
	static{
		System.loadLibrary("IAL");
		System.loadLibrary("SDL");
		System.loadLibrary("barcodereader");
	}
	
	/**
	 * #1:Scanner2DManager scanner2DManager = instance(context);
	 *  2:scanner2DManager.startScanner2D(scanner2DModeType);
	 */
	
	
	private static Scanner2D4500Manager scanner2D4500Manager;
	
	private BarCodeReader barCodeReader;
	private Context context;
	private Scanner2DCallback scanner2DCallback;

	
	private BarcodeInfo barcodeInfo;
	
	private Scanner2D4500Manager(Context context){
		this.context = context;
		scanner2DCallback = new Scanner2D4500(context);
		this.barCodeReader =getBarCodeReader();
	}
	
	public static Scanner2D4500Manager instance(Context context){
		if(scanner2D4500Manager==null){
			scanner2D4500Manager = new Scanner2D4500Manager(context);
		}
		return scanner2D4500Manager;
	}
	 
	@Override
	public void onPreviewFrame(byte[] data, BarCodeReader reader) {
		
	}

	@Override
	public void onPictureTaken(int format, int width, int height, byte[] data, BarCodeReader reader) {
		
	}

	@Override
	public void onDecodeComplete(int symbology, int length, byte[] data, BarCodeReader reader) {
		if (length > 0){
			if (symbology == 0x99){
				symbology = data[0];
				int n = data[1];
				int s = 2;
				int d = 0;
				int len = 0;
				byte d99[] = new byte[data.length];					
				for (int i=0; i<n; ++i)
				{
					s += 2;
					len = data[s++];
					System.arraycopy(data, s, d99, d, len);
					s += len;
					d += len;
				}
				d99[d] = 0;
				data = d99;
			}
			try {
				String encoding = StringUtils.guessEncoding(data);
				BarcodeInfo barcodeInfo = new BarcodeInfo();
				barcodeInfo.setCodeMessage(new String(data, 0, length, encoding));
				barcodeInfo.setCondeLength(length);
				barcodeInfo.setCodeType(getTypeName(Scanner2DBarcodeType.values(), symbology));
				setBarcodeInfo(barcodeInfo);
				scanner2DCallback.scanner2DGetDecode(barcodeInfo);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			
		}else{// no-decode
			switch (length) {
			case BarCodeReader.DECODE_STATUS_TIMEOUT:
				scanner2DCallback.scanner2DError("DECODE_STATUS_TIMEOUT");
				break;
			case BarCodeReader.DECODE_STATUS_CANCELED:
				scanner2DCallback.scanner2DError("DECODE_STATUS_CANCELED");
				break;
			case BarCodeReader.DECODE_STATUS_ERROR:
				scanner2DCallback.scanner2DError("DECODE_STATUS_ERROR");
				break;
			default:
				scanner2DCallback.scanner2DError("DECODE_FAILE");
				break;
			}
      }
	}

	@Override
	public void onEvent(int event, int info, byte[] data, BarCodeReader reader) {
		
	}
	
	protected synchronized BarCodeReader getBarCodeReader() {
		try {
			ReaderInfo readerInfo = new ReaderInfo();
			int numberOfReaders = BarCodeReader.getNumberOfReaders();
			if(numberOfReaders>0){
				if(barCodeReader==null){
					int readerId = 0;
					BarCodeReader.getReaderInfo(numberOfReaders-1, readerInfo);
					if(readerInfo.facing==ReaderInfo.BCRDR_FACING_FRONT){
						readerId = readerInfo.facing;
					}
					barCodeReader = BarCodeReader.open(readerId);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return barCodeReader;
	}
	
	public synchronized void startScanner2D(Scanner2DModeType scanner2DModeType){
		
		scanner2DCallback.scanner2DEnable();
		
		switch(scanner2DModeType){
		case MODE_DECODE:
			scanner2DDecode();
			break;
		case MODE_VIDEO:
			scanner2DVideo();
			break;
		case MODE_SNAPSHOT:
			scanner2DSnapshot();
			break;
		}
	}
	
	public void scanner2DDecode(){
		if(barCodeReader!=null){
			barCodeReader.setDecodeCallback(this);
			barCodeReader.setDefaultParameters();
			//barCodeReader.enableAllCodeTypes();
			barCodeReader.startDecode();
		}else{
			return;
		}
	}
	
	public void scanner2DVideo(){
		
	}
	
	public void scanner2DSnapshot(){
		
	}
	
	
	
	public BarcodeInfo getBarcodeInfo() {
		return barcodeInfo;
	}

	public void setBarcodeInfo(BarcodeInfo barcodeInfo) {
		this.barcodeInfo = barcodeInfo;
	}

	public String getTypeName(Scanner2DBarcodeType[] scanner2DBarcodeTypes,int symbology){
		for (Scanner2DBarcodeType scanner2DBarcodeType : scanner2DBarcodeTypes) {
			if(scanner2DBarcodeType.type==symbology){
				return scanner2DBarcodeType.name();
			}
		}
		return null;
	}
}
